#include "iot_errno.h"
#include "iot_pwm.h"
#include "stm32f4xx_ll_tim.h"
#include "stm32f4xx_ll_rcc.h"
#include "ll_gpio.h"
#include "ll_pwm.h"
#include "stdio.h"

extern PWM_Config g_pwmConfig[PWM_MAX];

unsigned int IoTPwmInit(unsigned int port)
{
    if (port>PWM_MAX || port<1) {
        printf("%s line %d error : bad pwm port, for stm32f407 pwm port is 1~31...\n", __func__, __LINE__);
        return IOT_FAILURE;
    }
    // 配置GPIO
    if(LL_PWM_PIN_CONFIG(port) != SUCCESS){
        printf("%s line %d error : config pwm pin failed...\n", __func__, __LINE__);
        return IOT_FAILURE;
    }
    // 使用默认的内部时钟
    LL_TIM_SetClockSource(g_pwmConfig[port-1].TIMx, LL_TIM_CLOCKSOURCE_INTERNAL);
    // 打开定时器时钟
    LL_TIM_EnableClock(g_pwmConfig[port-1].TIMx);
    // 禁用快速模式
    LL_TIM_OC_DisableFast(g_pwmConfig[port-1].TIMx, g_pwmConfig[port-1].channel);
    // 禁用输出触发功能，主从模式需要启动
    LL_TIM_SetTriggerOutput(g_pwmConfig[port-1].TIMx, LL_TIM_TRGO_RESET);
    // 禁用主从模式
    LL_TIM_DisableMasterSlaveMode(g_pwmConfig[port-1].TIMx);
    // 禁用预装载功能，这是无缓冲的，将立即装载而不等待更新事件
    LL_TIM_DisableARRPreload(g_pwmConfig[port-1].TIMx);
    // 启用PWM通道的预装载功能，以便波形更好
    LL_TIM_OC_EnablePreload(g_pwmConfig[port-1].TIMx, g_pwmConfig[port-1].channel);

    printf("**************************************************************************\n");
    printf("* PWM init success! Please attention to the following information...     *\n");
    printf("**************************************************************************\n");
    printf("* Use default config for PWM, see Tabel PWM-Pin.                         *\n");
    printf("* For stm32f407 pwm port is 1~31.                                        *\n");
    printf("* If you want change pwm pin, please modify global array :               *\n");
    printf("*      pwm_pin[], GPIO pins corresponding to PWM                         *\n");
    printf("*      pwm_tim[], Which TIM does PWM belong to                           *\n");
    printf("*      pwm_ch[],  The channel of PWM in TIM                              *\n");
    printf("**************************************************************************\n");
    return IOT_SUCCESS;
}

unsigned int IoTPwmDeinit(unsigned int port)
{
    if (port>PWM_MAX || port<1) {
        printf("%s line %d error : bad pwm port, for stm32f407 pwm port is 1~31...\n", __func__, __LINE__);
        return IOT_FAILURE;
    }
    // 复位timx
    if(LL_TIM_DeInit(g_pwmConfig[port-1].TIMx) != SUCCESS){
        printf("%s line %d error : pwm timx deinit failed...\n", __func__, __LINE__);
        return IOT_FAILURE;
    }
    // 复位gpio
    GPIO_TypeDef* GPIOx = LL_GET_GPIOX((g_pwmConfig[port-1].pin)/16);
    if(LL_GPIO_DeInit(GPIOx) != SUCCESS){
        printf("%s line %d error : pwm gpio pin deinit failed...\n", __func__, __LINE__);
        return IOT_FAILURE;
    }
    return IOT_SUCCESS;
}

unsigned int IoTPwmStart(unsigned int port, unsigned short duty, unsigned int freq)
{
    if (port>PWM_MAX || port<1) {
        printf("%s line %d error : bad pwm port, for stm32f407 pwm port is 1~31...\n", __func__, __LINE__);
        return IOT_FAILURE;
    }
    // 获取系统时钟
    LL_RCC_ClocksTypeDef rcc_clk;
    LL_RCC_GetSystemClocksFreq(&rcc_clk);

    LL_TIM_InitTypeDef TIM_InitStruct = {0};
    LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
    // 计算分频参数
    TIM_TypeDef *timx = g_pwmConfig[port-1].TIMx;
    if(timx==TIM2 || timx==TIM3 || timx==TIM4 || timx==TIM5 || timx==TIM12 || timx==TIM13 || timx==TIM14)
        CalPwmParam(rcc_clk.PCLK1_Frequency, duty, freq, &TIM_InitStruct.Prescaler, &TIM_InitStruct.Autoreload, &TIM_OC_InitStruct.CompareValue);
    else if(timx==TIM1 || timx==TIM8 || timx==TIM9 || timx==TIM10 || timx==TIM11)
        CalPwmParam(rcc_clk.PCLK2_Frequency, duty, freq, &TIM_InitStruct.Prescaler, &TIM_InitStruct.Autoreload, &TIM_OC_InitStruct.CompareValue);
    printf("%d %d %d %d\n", rcc_clk.PCLK2_Frequency, TIM_InitStruct.Prescaler, TIM_InitStruct.Autoreload, TIM_OC_InitStruct.CompareValue);
    /* TIM3初始化配置 */
    // 向上计数
    TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
    // 内部分频
    TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
    TIM_InitStruct.RepetitionCounter = 0;
    if(LL_TIM_Init(g_pwmConfig[port-1].TIMx, &TIM_InitStruct)!=SUCCESS){
        printf("%s line %d error : Init PWM TIMx failed...\n", __func__, __LINE__);
        return IOT_FAILURE;
    }
    // PWM模式1，TIMx_CNT<TIMx_CCRn时，输出有效电平
    TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
    // 禁止输出，通道启动后会自动打开
    TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE;
    TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE;
    // 高电平有效
    TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
    TIM_OC_InitStruct.OCNPolarity = LL_TIM_OCPOLARITY_HIGH;
    // 空闲状态为低电平
    TIM_OC_InitStruct.OCIdleState = LL_TIM_OCIDLESTATE_LOW;
    TIM_OC_InitStruct.OCNIdleState = LL_TIM_OCIDLESTATE_LOW;
    // 初始化输出比较通道
    if(LL_TIM_OC_Init(g_pwmConfig[port-1].TIMx, g_pwmConfig[port-1].channel, &TIM_OC_InitStruct)!=SUCCESS){
        printf("%s line %d error : Init PWM OC channel failed...\n", __func__, __LINE__);
        return IOT_FAILURE;
    }

    // 使能通道
    LL_TIM_CC_EnableChannel(g_pwmConfig[port-1].TIMx, g_pwmConfig[port-1].channel);
    LL_TIM_EnableAllOutputs(g_pwmConfig[port-1].TIMx);
    // 使能定时器
    LL_TIM_EnableCounter(g_pwmConfig[port-1].TIMx);
    //LL_TIM_GenerateEvent_UPDATE(g_pwmConfig[port-1].TIMx);
    return IOT_SUCCESS;
}

unsigned int IoTPwmStop(unsigned int port)
{
    if (port>PWM_MAX || port<1) {
        printf("%s line %d error : bad pwm port, for stm32f407 pwm port is 1~31...\n", __func__, __LINE__);
        return IOT_FAILURE;
    }
    // 禁用通道
    LL_TIM_CC_DisableChannel(g_pwmConfig[port-1].TIMx, g_pwmConfig[port-1].channel);
    // 禁止定时器
    LL_TIM_DisableCounter(g_pwmConfig[port-1].TIMx);

    return IOT_SUCCESS;
}
